﻿using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Examples.CAMLFilter
{
    class FilterEditor : EditorPart
    {
        private Locale locale = new Locale();


        // Ключ для хранения фильтров во ViewState
        private const string VS_Filters = "VS_CAMLFilters";

        private const string UpdatePanel_ID = "upCAMLFilterEditor";

        // Кастуем папу в нужный тип
        private CAMLFilter camlFilter
        {
            get { return this.WebPartToEdit as CAMLFilter; }
        }

        /// <summary>
        /// Хранилище редактируемых фильтров
        /// </summary>
        private List<Filter> filters = new List<Filter>();

        #region Controls

        // Общий контейнер
        UpdatePanel upWork;

        ListBox lbFilters;

        Button btnUp;
        Button btnDown;

        DropDownList ddlFields;
        DropDownList ddlConditions;

        DropDownList ddlValueSources;

        TextBox tbValue;

        CheckBox cbUseLookupId;
        CheckBox cbIncludeTimeValue;
        CheckBox cbAllowEmptyValue;
        CheckBox cbIsMulti;
        TextBox tbDelimiter;
        TextBox tbCAML;

        CheckBox cbIsActive;

        CheckBox cbUseOr;

        Button btnAddFilter;
        Button btnDeleteFilter;

        CheckBox cbDebug;

        CheckBox cbInfo;

        Label lChanged;

        PlaceHolder phFilterControls;

        Panel pFilterName;
        Panel pFilter;

        Panel pValueSources;
        Panel pValue;
        Panel pAllowEmptyValue;
        Panel pIsMulti;
        Panel pUseLookupId;
        Panel pIncludeTimeValue;

        Panel pCAML;

        Label lTitle;

        Label lFilterName;

        Label lVSHint;
        Label lCondHint;


        Label lErrors;


        HiddenField hfListId;

        #endregion Controls


        // Список, с которым работаем
        SPList list = null;

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (camlFilter.ListView != null)
            {
                phFilterControls.Visible = true;

                list = SPContext.Current.Web.Lists[camlFilter.ListView.ListId];

                lTitle.Text = String.Format(SPUtility.GetLocalizedString("$Resources:WPEConnected", "Examples.CAMLFilter", locale), list.Title, camlFilter.ListView.DisplayTitle) + "<br/>";

                // Заполняем контролы значениями

                hfListId.Value = camlFilter.ListView.ListId.ToString();

                // Список фильтров
                int idx = lbFilters.SelectedIndex;
                lbFilters.Items.Clear();
                lbFilters.Items.Add(new ListItem(SPUtility.GetLocalizedString("$Resources:WPNewFilter", "Examples.CAMLFilter", locale), ""));
                loadFiltersFromViewState();
                if (filters != null)
                {
                    for (int i = 0; i < filters.Count; i++)
                    {
                        lbFilters.Items.Add(new ListItem(filters[i].Title, i.ToString()));
                    }
                }
                lbFilters.SelectedIndex = (!Page.IsPostBack ? 0 : (idx < lbFilters.Items.Count ? idx : lbFilters.Items.Count - 1));

                // Заполняем списки редактора фильтра, если они пустые

                if (ddlFields.Items.Count == 0)
                    foreach (SPField field in list.Fields)
                    {
                        String ftype = Filter.GetFieldType(field);
                        if (!String.IsNullOrEmpty(ftype))
                            ddlFields.Items.Add(new ListItem(String.Format("{0} ({1}: {2})", field.Title, field.InternalName, ftype), String.Format("{0}|{1}", field.InternalName, ftype)));
                    }

                if (ddlConditions.Items.Count == 0)
                    foreach (Condition c in Enum.GetValues(typeof(Condition)))
                    {
                        ddlConditions.Items.Add(new ListItem(SPUtility.GetLocalizedString("$Resources:Condition" + c.ToString(), "Examples.CAMLFilter", locale), ((int)c).ToString()));
                    }


                if (ddlValueSources.Items.Count == 0)
                    foreach (ValueSource vs in Enum.GetValues(typeof(ValueSource)))
                    {
                        ddlValueSources.Items.Add(new ListItem(SPUtility.GetLocalizedString("$Resources:ValueSource" + vs.ToString(), "Examples.CAMLFilter", locale), ((int)vs).ToString()));
                    }


                // И включаем подходящие контролы
                if (lbFilters.SelectedItem != null)
                {

                    pFilterName.Visible = true;
                    pFilter.Visible = true;

                    // Выбран новый фильтр
                    if (String.IsNullOrEmpty(lbFilters.SelectedValue))
                    {
                        lFilterName.Text = SPEncode.HtmlEncode(lbFilters.SelectedItem.Text);

                        btnDeleteFilter.Visible = false;
                        btnAddFilter.Text = SPUtility.GetLocalizedString("$Resources:WPEAddFilter", "Examples.CAMLFilter", locale);

                        btnUp.Enabled = false;
                        btnDown.Enabled = false;

                    }
                    // Выбран существующий фильтр
                    else
                    {
                        lFilterName.Text = String.Format(SPUtility.GetLocalizedString("$Resources:WPEFilterName", "Examples.CAMLFilter", locale), SPEncode.HtmlEncode(lbFilters.SelectedItem.Text));

                        btnDeleteFilter.Visible = true;
                        btnAddFilter.Text = SPUtility.GetLocalizedString("$Resources:WPESaveFilter", "Examples.CAMLFilter", locale);


                        btnUp.Enabled = (lbFilters.SelectedIndex > 1);
                        btnDown.Enabled = (lbFilters.SelectedIndex < lbFilters.Items.Count - 1);

                    }

                }
                else
                {
                    btnUp.Enabled = false;
                    btnDown.Enabled = false;

                    pFilterName.Visible = false;
                    pFilter.Visible = false;
                }


            }
            else
            {
                lTitle.Text = SPUtility.GetLocalizedString("$Resources:WPENotConnected", "Examples.CAMLFilter", locale);
                phFilterControls.Visible = false;

            }

        }

        protected override void CreateChildControls()
        {
            try
            {

                base.CreateChildControls();

                upWork = new UpdatePanel() { ID = UpdatePanel_ID, UpdateMode = UpdatePanelUpdateMode.Conditional };


                hfListId = new HiddenField() { ID = "hfListId" };
                upWork.ContentTemplateContainer.Controls.Add(hfListId);

                // Заголовок 
                Panel pTitle = new Panel() { CssClass = "UserSectionHead" };
                lTitle = new Label() { ID = "lTitle" };
                pTitle.Controls.Add(lTitle);
                upWork.ContentTemplateContainer.Controls.Add(pTitle);

                #region Общая панель фильтров

                phFilterControls = new PlaceHolder();

                // Блок списка фильтров

                Panel pFiltersGroup = new Panel() { CssClass = "UserSectionBody" };
                Panel pFilters = new Panel() { CssClass = "UserControlGroup" };
                Table tblFilters = new Table() { CellPadding = 0, CellSpacing = 0 };
                TableRow rFilters = new TableRow();
                TableCell c1Filters = new TableCell() { VerticalAlign = VerticalAlign.Top };
                TableCell c2Filters = new TableCell() { VerticalAlign = VerticalAlign.Top };

                rFilters.Cells.Add(c1Filters);
                rFilters.Cells.Add(c2Filters);
                tblFilters.Rows.Add(rFilters);

                lbFilters = new ListBox() { ID = "lbFilter", Rows = 10, SelectionMode = ListSelectionMode.Single, CssClass = "UserInput" }; //AutoPostBack = true, но делаем сами, чтобы отследить изменение параметров фильтра
                lbFilters.SelectedIndexChanged += new EventHandler(lbFilters_SelectedIndexChanged);
                lbFilters.Attributes.Add("onchange", "filterPostback();");

                c1Filters.Controls.Add(lbFilters);

                btnUp = new Button() { ID = "btnUp", Width = Unit.Pixel(80), Text = SPUtility.GetLocalizedString("$Resources:WPEUp", "Examples.CAMLFilter", locale), CssClass = "UserButton" };
                btnUp.Click += new EventHandler(btnUp_Click);
                btnUp.OnClientClick = "return confirmChange();";

                btnDown = new Button() { ID = "btnDown", Width = Unit.Pixel(80), Text = SPUtility.GetLocalizedString("$Resources:WPEDown", "Examples.CAMLFilter", locale), CssClass = "UserButton" };
                btnDown.Click += new EventHandler(btnDown_Click);
                btnDown.OnClientClick = "return confirmChange();";

                c2Filters.Controls.Add(new LiteralControl("&nbsp;"));
                c2Filters.Controls.Add(btnUp);
                c2Filters.Controls.Add(new LiteralControl("<br/>&nbsp;"));
                c2Filters.Controls.Add(btnDown);

                pFilters.Controls.Add(tblFilters);


                pFilters.Controls.Add(new LiteralControl("<br/>"));

                // Как объединять фильтры
                cbUseOr = new CheckBox() { ID = "cbUseOr", Text = SPUtility.GetLocalizedString("$Resources:WPEUseOr", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                pFilters.Controls.Add(cbUseOr);

                pFiltersGroup.Controls.Add(pFilters);
                phFilterControls.Controls.Add(pFiltersGroup);


                // Блок настройки конкретного фильтра

                // Название фильтра
                pFilterName = new Panel() { CssClass = "UserSectionHead" };
                lFilterName = new Label() { ID = "lFilterName" };
                pFilterName.Controls.Add(lFilterName);

                lChanged = new Label() { ID = "lChanged", Text = "<font color='red'>*</font>" };
                pFilterName.Controls.Add(lChanged);

                phFilterControls.Controls.Add(pFilterName);

                // Поля фильтра
                pFilter = new Panel { CssClass = "UserSectionBody" };

                // Имя поля
                Panel pFields = new Panel() { CssClass = "UserControlGroup" };
                pFields.Controls.Add(new Label() { Text = SPUtility.GetLocalizedString("$Resources:WPEFieldName", "Examples.CAMLFilter", locale) + "<br/>" });
                ddlFields = new DropDownList() { ID = "ddlFields", CssClass = "UserInput" };
                ddlFields.Attributes.Add("onchange", "changeFilter();redrawFilter();");
                pFields.Controls.Add(ddlFields);

                pFilter.Controls.Add(pFields);

                // Условия
                Panel pConditions = new Panel() { CssClass = "UserControlGroup" };
                pConditions.Controls.Add(new Label() { Text = SPUtility.GetLocalizedString("$Resources:WPECondition", "Examples.CAMLFilter", locale) + "<br/>" });
                ddlConditions = new DropDownList() { ID = "ddlConditions", CssClass = "UserInput" };
                ddlConditions.Attributes.Add("onchange", "changeFilter();redrawFilter();");
                pConditions.Controls.Add(ddlConditions);
                pConditions.Controls.Add(new LiteralControl("<br/>"));
                lCondHint = new Label() { ID = "lCondHint" };
                lCondHint.Font.Size = FontUnit.XXSmall;
                pConditions.Controls.Add(lCondHint);

                pFilter.Controls.Add(pConditions);

                // Источник значения
                pValueSources = new Panel() { CssClass = "UserControlGroup" };
                pValueSources.Controls.Add(new Label() { Text = SPUtility.GetLocalizedString("$Resources:WPEValueSource", "Examples.CAMLFilter", locale) + "<br/>" });
                ddlValueSources = new DropDownList() { ID = "ddlValueSources", CssClass = "UserInput" };
                ddlValueSources.Attributes.Add("onchange", "changeFilter();redrawFilter();");
                pValueSources.Controls.Add(ddlValueSources);
                pValueSources.Controls.Add(new LiteralControl("<br/>"));
                lVSHint = new Label() { ID = "lVSHint" };
                lVSHint.Font.Size = FontUnit.XXSmall;
                pValueSources.Controls.Add(lVSHint);

                pFilter.Controls.Add(pValueSources);

                // Значение
                pValue = new Panel() { CssClass = "UserControlGroup" };
                pValue.Controls.Add(new Label() { Text = SPUtility.GetLocalizedString("$Resources:WPEValue", "Examples.CAMLFilter", locale) + "<br/>" });
                tbValue = new TextBox() { ID = "tbValue", Columns = 50, CssClass = "UserInput" };
                tbValue.Attributes.Add("onchange", "changeFilter();");
                pValue.Controls.Add(tbValue);

                pFilter.Controls.Add(pValue);

                // Использовать LookupId
                pUseLookupId = new Panel() { CssClass = "UserControlGroup" };
                cbUseLookupId = new CheckBox() { ID = "cbUseLookupId", Text = SPUtility.GetLocalizedString("$Resources:WPEUseLookupId", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                cbUseLookupId.InputAttributes.Add("onclick", "changeFilter();");
                pUseLookupId.Controls.Add(cbUseLookupId);

                pFilter.Controls.Add(pUseLookupId);

                // Учитывать значение времени
                pIncludeTimeValue = new Panel() { CssClass = "UserControlGroup" };
                cbIncludeTimeValue = new CheckBox() { ID = "cbIncludeTimeValue", Text = SPUtility.GetLocalizedString("$Resources:WPEIncludeTimeValue", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                cbIncludeTimeValue.InputAttributes.Add("onclick", "changeFilter();");
                pIncludeTimeValue.Controls.Add(cbIncludeTimeValue);

                pFilter.Controls.Add(pIncludeTimeValue);



                // Непустое значение
                pAllowEmptyValue = new Panel() { CssClass = "UserControlGroup" };
                cbAllowEmptyValue = new CheckBox() { ID = "cbAllowEmptyValue", Text = SPUtility.GetLocalizedString("$Resources:WPEAllowEmptyValue", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                cbAllowEmptyValue.InputAttributes.Add("onclick", "changeFilter();");
                pAllowEmptyValue.Controls.Add(cbAllowEmptyValue);

                pFilter.Controls.Add(pAllowEmptyValue);

                // Разрешены ли множественные значения
                pIsMulti = new Panel() { CssClass = "UserControlGroup" };
                cbIsMulti = new CheckBox() { ID = "cbIsMulti", Text = SPUtility.GetLocalizedString("$Resources:WPEIsMulti", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                cbIsMulti.InputAttributes.Add("onclick", "changeFilter();redrawFilter();");
                pIsMulti.Controls.Add(cbIsMulti);
                pIsMulti.Controls.Add(new LiteralControl("&nbsp;"));
                tbDelimiter = new TextBox() { ID = "tbDelimiter", Columns = 5, CssClass = "UserInput" };
                tbDelimiter.Attributes.Add("onchange", "changeFilter();");
                pIsMulti.Controls.Add(tbDelimiter);

                pFilter.Controls.Add(pIsMulti);

                // CAML-запрос
                pCAML = new Panel() { CssClass = "UserControlGroup" };
                pCAML.Controls.Add(new Label() { Text = SPUtility.GetLocalizedString("$Resources:WPECAML", "Examples.CAMLFilter", locale) + "<br/>" });
                tbCAML = new TextBox() { ID = "tbCAML", TextMode = TextBoxMode.MultiLine, Columns = 50, Rows = 5, CssClass = "UserInput" };
                tbCAML.Attributes.Add("onchange", "changeFilter();");
                pCAML.Controls.Add(tbCAML);
                Label lCAMLHint = new Label() { Text = "<br/>" + SPUtility.GetLocalizedString("$Resources:WPEHintCAML", "Examples.CAMLFilter", locale) };
                lCAMLHint.Font.Size = FontUnit.XXSmall;
                pCAML.Controls.Add(lCAMLHint);

                pFilter.Controls.Add(pCAML);

                // Признак активности
                Panel pIsActive = new Panel() { CssClass = "UserControlGroup" };
                cbIsActive = new CheckBox() { ID = "cbIsActive", Text = SPUtility.GetLocalizedString("$Resources:WPEIsActive", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                cbIsActive.InputAttributes.Add("onclick", "changeFilter();");
                pIsActive.Controls.Add(cbIsActive);
                pFilter.Controls.Add(pIsActive);

                // Конпки-экшны (и рядом - updateprogress)
                Panel pButtons = new Panel() { CssClass = "UserControlGroup" };
                Table tblButtons = new Table() { CellPadding = 0, CellSpacing = 0 };
                TableRow rButtons = new TableRow();
                TableCell c1Buttons = new TableCell();
                TableCell c2Buttons = new TableCell();
                rButtons.Cells.Add(c1Buttons);
                rButtons.Cells.Add(c2Buttons);
                tblButtons.Rows.Add(rButtons);

                btnAddFilter = new Button() { ID = "btnAddFilter", Width = Unit.Pixel(80), Text = SPUtility.GetLocalizedString("$Resources:WPEAddFilter", "Examples.CAMLFilter", locale), CssClass = "UserButton" };
                btnAddFilter.Click += new EventHandler(btnAddFilter_Click);
                btnAddFilter.OnClientClick = "return confirmSave();";

                btnDeleteFilter = new Button() { ID = "btnDeleteFilter", Width = Unit.Pixel(80), Text = SPUtility.GetLocalizedString("$Resources:WPEDeleteFilter", "Examples.CAMLFilter", locale), CssClass = "UserButton" };
                btnDeleteFilter.Click += new EventHandler(btnDeleteFilter_Click);
                btnDeleteFilter.OnClientClick = "return confirmDelete();";

                c1Buttons.Controls.Add(btnAddFilter);
                c1Buttons.Controls.Add(new LiteralControl("&nbsp;"));
                c1Buttons.Controls.Add(btnDeleteFilter);
                c1Buttons.Controls.Add(new LiteralControl("&nbsp;"));

                UpdateProgress upProgress = new UpdateProgress() { AssociatedUpdatePanelID = UpdatePanel_ID, ProgressTemplate = new ProgressTemplate(SPUtility.GetLocalizedString("$Resources:WPEWait", "Examples.CAMLFilter", locale)) };
                c2Buttons.Controls.Add(upProgress);

                pButtons.Controls.Add(tblButtons);

                pFilter.Controls.Add(pButtons);

                // Панель с ошибками
                Panel pError = new Panel() { CssClass = "UserControlGroup" };
                lErrors = new Label() { ID = "lError" };
                pError.Controls.Add(lErrors);
                pFilter.Controls.Add(pError);

                phFilterControls.Controls.Add(pFilter);


                #endregion Общая панель фильтров

                upWork.ContentTemplateContainer.Controls.Add(phFilterControls);


                upWork.ContentTemplateContainer.Controls.Add(new Panel() { CssClass = "UserDottedLine", Width = Unit.Percentage(100) });


                // Блок "Show info"
                Panel pInfo = new Panel() { CssClass = "UserSectionBody" };
                cbInfo = new CheckBox() { ID = "cbInfo", Text = SPUtility.GetLocalizedString("$Resources:WPEInfo", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                pInfo.Controls.Add(cbInfo);

                upWork.ContentTemplateContainer.Controls.Add(pInfo);

                // Блок "Debug info"
                Panel pDebug = new Panel() { CssClass = "UserSectionBody" };
                cbDebug = new CheckBox() { ID = "cbDebug", Text = SPUtility.GetLocalizedString("$Resources:WPEDebug", "Examples.CAMLFilter", locale), CssClass = "UserInput" };
                pDebug.Controls.Add(cbDebug);

                upWork.ContentTemplateContainer.Controls.Add(pDebug);

                this.Controls.Add(upWork);

                loadFiltersFromViewState();

                #region Scripts

                // Добавляем скрипты для отрисовки контролов
                ClientScriptManager cs = Page.ClientScript;
                Type csType = this.GetType();

                // Сгенерим предварительно массивы значений
                String vsHints = String.Format(@"
var VSHints = {{
    '" + (int)ValueSource.Constant + @"' : '{0}', 
    '" + (int)ValueSource.Request + @"' : '{1}',
    '" + (int)ValueSource.URL + @"' : '{2}',
    '" + (int)ValueSource.Form + @"' : '{3}',
    '" + (int)ValueSource.Cookie + @"' : '{4}'
}};",
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEVSHintConstant", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEVSHintRequest", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEVSHintURL", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEVSHintForm", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEVSHintCookie", "Examples.CAMLFilter", locale))
);

                String condHints = String.Format(@"
var CondHints = {{
    '" + (int)Condition.Eq + @"' : ['{0}', '{1}'], 
    '" + (int)Condition.Neq + @"' : ['{2}', '{3}'],
    '" + (int)Condition.Gt + @"' : ['{4}', ''],
    '" + (int)Condition.Geq + @"' : ['{5}', ''],
    '" + (int)Condition.Lt + @"' : ['{6}', ''],
    '" + (int)Condition.Leq + @"' : ['{7}', ''],
    '" + (int)Condition.IsNull + @"' : ['{8}', ''],
    '" + (int)Condition.IsNotNull + @"' : ['{9}', ''],
    '" + (int)Condition.BeginsWith + @"' : ['{10}', '{11}'],
    '" + (int)Condition.Contains + @"' : ['{12}', '{13}'],
    '" + (int)Condition.In + @"' : ['{14}', ''],
    '" + (int)Condition.Includes + @"' : ['{15}', '{16}'],
    '" + (int)Condition.NotIncludes + @"' : ['{17}', '{18}'],
    '" + (int)Condition.AllIncludes + @"' : ['{19}', ''],
    '" + (int)Condition.AllNotIncludes + @"' : ['{20}', ''],
    '" + (int)Condition.Between + @"' : ['{21}', ''],
    '" + (int)Condition.NotBetween + @"' : ['{22}', ''],
    '" + (int)Condition.CAML + @"' : ['{23}', '']
}};",
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintEq", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondMultiHintEq", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintNeq", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondMultiHintNeq", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintGt", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintGeq", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintLt", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintLeq", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintIsNull", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintIsNotNull", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintBeginsWith", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondMultiHintBeginsWith", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintContains", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondMultiHintContains", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintIn", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintIncludes", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondMultiHintIncludes", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintNotIncludes", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondMultiHintNotIncludes", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintAllIncludes", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintAllNotIncludes", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintBetweens", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintNotBetweens", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPECondHintCAML", "Examples.CAMLFilter", locale))
);


                String scripts = @"
<script type='text/javascript'>

var lbFilters;
var ddlFields;
var ddlConditions;
var ddlSources;
var pValue;
var pAllowEmptyValue;
var pIsMulti;
var pIncludeTimeValue;
var pCAML;
var cbIsMulti;
var tbDelimiter;
var lVSHint;
var lCondHint;
var lChanged;

var idxCurrentFilter;
var filterChanged;

// Имплементация format для строк
String.prototype.format = function () {{
    var args = arguments;
    return this.replace(/\{{\{{|\}}\}}|\{{(\d+)\}}/g, function (m, n) {{
        if (m == '{{{{') {{ return '{{'; }}
        if (m == '}}}}') {{ return '}}'; }}
        return args[n];
    }});
    
}};


// Перерисовка объектов при смене параметров
function redrawFilter()
{{
    lbFilters = document.getElementById('{0}');
    ddlFields = document.getElementById('{1}');
    ddlConditions = document.getElementById('{2}');
    ddlSources = document.getElementById('{3}');
    pValue = document.getElementById('{4}');
    pUseLookupId = document.getElementById('{5}');
    pIncludeTimeValue = document.getElementById('{6}');
    pAllowEmptyValue = document.getElementById('{7}');
    pIsMulti = document.getElementById('{8}');
    pCAML = document.getElementById('{9}');
    cbIsMulti = document.getElementById('{10}');
    tbDelimiter = document.getElementById('{11}');
    lVSHint = document.getElementById('{12}');
    lCondHint = document.getElementById('{13}');
  
  
    if (ddlConditions.selectedIndex != -1 && ddlSources.selectedIndex != -1) 
    {{

        // Прячем настройки значения в зависимости от типа фильтра
        switch (ddlConditions.options[ddlConditions.selectedIndex].value)
        {{

            case '" + (int)Condition.IsNull + @"':
            case '" + (int)Condition.IsNotNull + @"':
                pValue.style.display = (ddlSources.options[ddlSources.selectedIndex].value == '1') ? 'none' : '';
                pAllowEmptyValue.style.display = 'none';
                pIsMulti.style.display = 'none';
                pUseLookupId.style.display = 'none';
                pCAML.style.display = 'none';
                break;

            case '" + (int)Condition.Gt + @"':
            case '" + (int)Condition.Geq + @"':
            case '" + (int)Condition.Lt + @"':
            case '" + (int)Condition.Leq + @"':
                pAllowEmptyValue.style.display = '';
                pIsMulti.style.display = 'none';
                pUseLookupId.style.display = '';
                pCAML.style.display = 'none';
                break;

            case '" + (int)Condition.Between + @"':
            case '" + (int)Condition.NotBetween + @"':
            case '" + (int)Condition.In + @"':
            case '" + (int)Condition.AllIncludes + @"':
            case '" + (int)Condition.AllNotIncludes + @"':
                pAllowEmptyValue.style.display = 'none';
                pIsMulti.style.display = '';
                cbIsMulti.checked = true;
                pUseLookupId.style.display = '';
                pCAML.style.display = 'none';
                break;

            case '" + (int)Condition.CAML + @"':
                pAllowEmptyValue.style.display = '';
                pIsMulti.style.display = '';
                pUseLookupId.style.display = 'none';
                pCAML.style.display = '';
                break;

            default:
                pValue.style.display = '';
                pAllowEmptyValue.style.display = '';
                pIsMulti.style.display = '';
                pUseLookupId.style.display = '';
                pCAML.style.display = 'none';
        }}

        // Здесь дополнительно уберем контролы в зависимости от типа значений
        var fType = (ddlFields.selectedIndex != -1) ? ddlFields.options[ddlFields.selectedIndex].value.split('|')[1] : '';

        if (fType != '" + SPFieldType.Lookup + @"' && fType != '" + SPFieldType.User + @"')
                pUseLookupId.style.display = 'none';

        pIncludeTimeValue.style.display = (fType != '" + SPFieldType.DateTime + @"') ? 'none' : '';

        // Если указали мультизначения, заполним пустой разделитель
        if (cbIsMulti.checked && tbDelimiter.value.length == 0)
            tbDelimiter.value = '{16}';

        // Выдадим подсказку по источникам значений
        lVSHint.innerText = VSHints[ddlSources.options[ddlSources.selectedIndex].value];

        // Выдадим подсказку по условию
        lCondHint.innerText =  CondHints[ddlConditions.options[ddlConditions.selectedIndex].value][(cbIsMulti.checked &&  CondHints[ddlConditions.options[ddlConditions.selectedIndex].value][1]!= '') ? 1 : 0];

    }}

}}


// Обработчик lbFilters
function filterPostback()
{{
    lbFilters = document.getElementById('{0}');

    if (confirmChange()) {{
        idxCurrentFilter =  lbFilters.selectedIndex; 
        __doPostBack(lbFilters.name,'');
    }}
    else 
    {{ 
        lbFilters.selectedIndex = idxCurrentFilter; 
    }}
}}

function changeFilter()
{{
    lbFilters = document.getElementById('{0}');
    lChanged = document.getElementById('{14}');
    btnSaveFilter = document.getElementById('{15}');

    if (lbFilters.selectedIndex != -1 && lbFilters.options[lbFilters.selectedIndex].value != '')
    {{
        lChanged.style.display = '';
        btnSaveFilter.disabled = false;
        filterChanged = true;
    }}
}}


// Запрос на сохранение фильтра
function confirmSave()
{{
    lbFilters = document.getElementById('{0}');

    if (lbFilters.selectedIndex != -1 && lbFilters.options[lbFilters.selectedIndex].value != '')
        return confirm('{17}'.format(lbFilters.options[lbFilters.selectedIndex].text));
    else
        return true;
}}
// Запрос на удаление фильтра
function confirmDelete()
{{
    lbFilters = document.getElementById('{0}');

    if (lbFilters.selectedIndex != -1 && lbFilters.options[lbFilters.selectedIndex].value != '')
        return confirm('{18}'.format(lbFilters.options[lbFilters.selectedIndex].text));
    else
        return false;
}}

// Запрос на смену фильтра
function confirmChange()
{{
    lbFilters = document.getElementById('{0}');

    if (idxCurrentFilter != -1 && lbFilters.options[idxCurrentFilter].value != '' && filterChanged)
        return confirm('{19}'.format(lbFilters.options[idxCurrentFilter].text));
    else
        return true;
}}

// Перерисовка объектов при postback-ах
function pageLoad(){{

    lbFilters = document.getElementById('{0}');
    lChanged = document.getElementById('{14}');
    btnSaveFilter = document.getElementById('{15}');

    // Сбрасываем признак изменения
    if (lChanged != null) lChanged.style.display = 'none';
    if (btnSaveFilter != null) btnSaveFilter.disabled = (lbFilters.selectedIndex != -1 && lbFilters.options[lbFilters.selectedIndex].value != '');

    idxCurrentFilter = lbFilters.selectedIndex;
    filterChanged = false;

    redrawFilter();
}}

// Строки с подсказками для источников значений
{20}

// Строки с подсказками для условий
{21}


</script>";

                // Скрипт отрисовывает контролы в зависимости от выбранных значений
                if (!cs.IsClientScriptBlockRegistered(csType, "CAMLFilterScripts"))
                {
                    cs.RegisterClientScriptBlock(csType, "CAMLFilterScripts",
String.Format(scripts,
lbFilters.ClientID,
ddlFields.ClientID,
ddlConditions.ClientID,
ddlValueSources.ClientID,
pValue.ClientID,
pUseLookupId.ClientID,
pIncludeTimeValue.ClientID,
pAllowEmptyValue.ClientID,
pIsMulti.ClientID,
pCAML.ClientID,
cbIsMulti.ClientID,
tbDelimiter.ClientID,
lVSHint.ClientID,
lCondHint.ClientID,
lChanged.ClientID,
btnAddFilter.ClientID,
JSEncodeValue(Filter.DefaultDelimiter),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEQSaveFilter", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEQDeleteFilter", "Examples.CAMLFilter", locale)),
JSEncodeValue(SPUtility.GetLocalizedString("$Resources:WPEQChangeFilter", "Examples.CAMLFilter", locale)),
vsHints,
condHints
));
                }
                #endregion Scripts





            }
            catch (Exception ex)
            {
                this.Controls.Add(new LiteralControl(String.Format(SPUtility.GetLocalizedString("$Resources:ErrorPrompt", "Examples.CAMLFilter", locale), ex.Message) + "<br/>"));
            }
        }


        #region Event handlers

        // Инитим значения из параметров фильтра
        void lbFilters_SelectedIndexChanged(object sender, EventArgs e)
        {
            lErrors.Text = String.Empty;

            if (lbFilters.SelectedItem != null)
            {
                if (!String.IsNullOrEmpty(lbFilters.SelectedValue))
                {
                    int i = Int32.Parse(lbFilters.SelectedValue);

                    loadFiltersFromViewState();

                    string fval = String.Format("{0}|{1}", filters[i].FieldName, filters[i].FieldType);

                    if (ddlFields.Items.FindByValue(fval) == null)
                        lErrors.Text += String.Format(SPUtility.GetLocalizedString("$Resources:ErrBadFilterColumn", "Examples.CAMLFilter", locale), filters[i].FieldName, filters[i].FieldType) + " ";
                    else
                        ddlFields.SelectedValue = fval;

                    ddlConditions.SelectedValue = ((int)filters[i].Condition).ToString();
                    ddlValueSources.SelectedValue = ((int)filters[i].Source).ToString();
                    tbValue.Text = filters[i].Value;
                    cbUseLookupId.Checked = filters[i].UseLookupId;
                    cbIncludeTimeValue.Checked = filters[i].IncludeTimeValue;
                    cbIsMulti.Checked = filters[i].IsMulti;
                    tbDelimiter.Text = filters[i].Delimiter;
                    cbAllowEmptyValue.Checked = filters[i].AllowEmptyValue;
                    cbIsActive.Checked = filters[i].IsActive;
                    tbCAML.Text = filters[i].CAML;
                }
                else
                    cbIsActive.Checked = true;
            }

        }

        void btnAddFilter_Click(object sender, EventArgs e)
        {
            lErrors.Text = String.Empty;

            Condition condition = (Condition)Int32.Parse(ddlConditions.SelectedValue);
            ValueSource source = (ValueSource)Int32.Parse(ddlValueSources.SelectedValue);

            // Проверяем обязательные поля и выдаем ошибки

            // Заполнен ли разделитель?
            if ((condition == Condition.Between || condition == Condition.NotBetween))
            {
                if (!cbIsMulti.Checked)
                    lErrors.Text += SPUtility.GetLocalizedString("$Resources:ErrNeedMulti", "Examples.CAMLFilter", locale) + " ";
            }

            // Обязательно ли значение?
            if (String.IsNullOrEmpty(tbValue.Text) &&
                // Еси значение не задано прямо - всегда требуем имя параметра
                (source != ValueSource.Constant ||
                // Для явно заданных значений
                // Условия, для которых не требуются значения
                (condition != Condition.IsNull && condition != Condition.IsNotNull &&
                // Можно не задавать значения
                !cbAllowEmptyValue.Checked)
                ))
            {
                lErrors.Text += SPUtility.GetLocalizedString("$Resources:ErrNeedValue", "Examples.CAMLFilter", locale) + " ";
            }

            // Заполнен ли разделитель?
            if (cbIsMulti.Checked && String.IsNullOrEmpty(tbDelimiter.Text))
            {
                lErrors.Text += SPUtility.GetLocalizedString("$Resources:ErrNeedDelimiter", "Examples.CAMLFilter", locale) + " ";
            }

            if (!String.IsNullOrEmpty(lErrors.Text)) return;


            loadFiltersFromViewState();

            // Добавляем фильтр
            string[] fieldparams = ddlFields.SelectedValue.Split(new char[] { '|' });

            Filter filter = new Filter(fieldparams[0], fieldparams[1], condition, tbValue.Text, source, cbIsMulti.Checked, tbDelimiter.Text, cbAllowEmptyValue.Checked, cbUseLookupId.Checked, cbIncludeTimeValue.Checked, cbIsActive.Checked, tbCAML.Text);

            if (String.IsNullOrEmpty(lbFilters.SelectedValue))
            {
                if (filters == null)
                    filters = new List<Filter>();
                filters.Add(filter);
            }
            else
                filters[Int32.Parse(lbFilters.SelectedValue)] = filter;

            saveFiltersToViewState();
        }

        void btnDeleteFilter_Click(object sender, EventArgs e)
        {
            lErrors.Text = String.Empty;

            // Удаляем фильтр
            if (!String.IsNullOrEmpty(lbFilters.SelectedValue))
            {
                loadFiltersFromViewState();
                filters.RemoveAt(Int32.Parse(lbFilters.SelectedValue));
                saveFiltersToViewState();

                lbFilters.SelectedIndex--;
                lbFilters_SelectedIndexChanged(null, null);
            }
        }

        // Перемещения фильтров в списке
        void btnUp_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(lbFilters.SelectedValue))
            {
                int idx = Int32.Parse(lbFilters.SelectedValue);
                if (idx > 0)
                {
                    loadFiltersFromViewState();
                    Filter f = filters[idx - 1];
                    filters[idx - 1] = filters[idx];
                    filters[idx] = f;
                    saveFiltersToViewState();

                    lbFilters.SelectedIndex--;
                    lbFilters_SelectedIndexChanged(null, null);
                }

            }
        }

        void btnDown_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(lbFilters.SelectedValue))
            {
                int idx = Int32.Parse(lbFilters.SelectedValue);
                if (idx < filters.Count - 1)
                {
                    loadFiltersFromViewState();
                    Filter f = filters[idx + 1];
                    filters[idx + 1] = filters[idx];
                    filters[idx] = f;
                    saveFiltersToViewState();

                    lbFilters.SelectedIndex++;
                    lbFilters_SelectedIndexChanged(null, null);
                }

            }
        }

        #endregion Event handlers

        #region EditorPart abstracts implementation

        public override void SyncChanges()
        {
            EnsureChildControls();

            if (cbDebug != null)
                cbDebug.Checked = camlFilter.ShowDebug;

            if (cbInfo!= null)
                cbInfo.Checked = camlFilter.ShowInfo;

            if (cbUseOr != null)
                cbUseOr.Checked = camlFilter.UseOrConnections;

            filters = camlFilter.Filters;

            saveFiltersToViewState();
        }

        public override bool ApplyChanges()
        {
            //call to make sure the check box list is set up
            EnsureChildControls();

            loadFiltersFromViewState();

            if (cbDebug != null)
                camlFilter.ShowDebug = cbDebug.Checked;

            if (cbInfo!= null)
                camlFilter.ShowInfo = cbInfo.Checked;

            if (cbUseOr != null)
                camlFilter.UseOrConnections = cbUseOr.Checked;

            camlFilter.Filters = filters;

            camlFilter.ListId = String.IsNullOrEmpty(hfListId.Value) ? Guid.Empty : new Guid(hfListId.Value);

            return true;
        }

        #endregion  EditorPart abstracts implementation

        #region ProgressTemplate class implementation

        private class ProgressTemplate : ITemplate
        {
            public ProgressTemplate(string displayText)
            {
                DisplayText = displayText;

            }

            public void InstantiateIn(Control container)
            {
                if (!String.IsNullOrEmpty(DisplayText))
                    container.Controls.Add(new LiteralControl(DisplayText));
            }

            public string DisplayText { get; set; }
        }
        #endregion ProgressTemplate class implementation

        #region Helpers

        private void loadFiltersFromViewState()
        {
            if (ViewState[VS_Filters] != null)
                filters = ViewState[VS_Filters] as List<Filter>;
        }

        private void saveFiltersToViewState()
        {
            ViewState[VS_Filters] = filters;
        }

        static private String JSEncodeValue(String str)
        {
            String res = str;
            res = res.Replace("\\", "\\\\");
            res = res.Replace("'", "\\'");
            return res;
        }

        #endregion Helpers

    }


}
